/*!
 * \file test_spin_mutex.cpp
 * \brief SpinMutex工具类的单元测试
 * 
 * \details 测试SpinMutex类的所有功能，包括：
 *          - 自旋锁的基本加锁解锁操作
 *          - RAII锁管理器的功能
 *          - 多线程并发访问测试
 *          - 性能特性验证
 *          - 异常安全性测试
 */

#include <gtest/gtest.h>
#include <thread>
#include <vector>
#include <chrono>
#include <atomic>
#include "SpinMutex.hpp"

/*!
 * \brief SpinMutex测试夹具类
 * 
 * \details 为SpinMutex测试提供统一的测试环境
 */
class SpinMutexTest : public ::testing::Test {
protected:
    void SetUp() override {
        // 初始化测试环境
        shared_counter = 0;
        test_iterations = 10000;
    }

    void TearDown() override {
        // 清理测试环境
    }

    SpinMutex spin_mutex;
    std::atomic<int> shared_counter;
    int test_iterations;
};

/*!
 * \brief 测试SpinMutex基本加锁解锁功能
 * 
 * \details 验证SpinMutex的基本lock和unlock操作
 */
TEST_F(SpinMutexTest, TestBasicLockUnlock) {
    // 测试基本的加锁解锁操作
    EXPECT_NO_THROW({
        spin_mutex.lock();
        spin_mutex.unlock();
    });
    
    // 测试多次加锁解锁
    for (int i = 0; i < 10; ++i) {
        spin_mutex.lock();
        // 在锁保护下执行一些操作
        volatile int temp = i * 2;
        (void)temp;  // 避免未使用变量警告
        spin_mutex.unlock();
    }
}

/*!
 * \brief 测试SpinLock RAII管理器
 * 
 * \details 验证SpinLock的自动锁管理功能
 */
TEST_F(SpinMutexTest, TestSpinLockRAII) {
    // 测试RAII锁管理器的基本功能
    {
        SpinLock lock(spin_mutex);
        // 锁应该在这里被自动获取
        volatile int temp = 42;
        (void)temp;
    }
    // 锁应该在这里被自动释放
    
    // 测试嵌套作用域
    {
        SpinLock lock1(spin_mutex);
        {
            // 注意：SpinMutex不是递归锁，这里不能再次加锁同一个mutex
            // 但可以测试作用域结束时的自动解锁
            volatile int temp = 123;
            (void)temp;
        }
    }
}

/*!
 * \brief 测试多线程并发访问
 * 
 * \details 验证SpinMutex在多线程环境下的正确性
 */
TEST_F(SpinMutexTest, TestMultiThreadAccess) {
    const int num_threads = 4;
    const int increments_per_thread = 1000;
    std::vector<std::thread> threads;
    
    // 创建多个线程，每个线程对共享计数器进行增量操作
    for (int i = 0; i < num_threads; ++i) {
        threads.emplace_back([this, increments_per_thread]() {
            for (int j = 0; j < increments_per_thread; ++j) {
                SpinLock lock(spin_mutex);
                shared_counter++;
            }
        });
    }
    
    // 等待所有线程完成
    for (auto& thread : threads) {
        thread.join();
    }
    
    // 验证最终结果
    int expected_value = num_threads * increments_per_thread;
    EXPECT_EQ(shared_counter.load(), expected_value);
}

/*!
 * \brief 测试高并发场景
 * 
 * \details 验证SpinMutex在高并发情况下的性能和正确性
 */
TEST_F(SpinMutexTest, TestHighConcurrency) {
    const int num_threads = std::thread::hardware_concurrency();
    const int operations_per_thread = 500;
    std::vector<std::thread> threads;
    std::atomic<int> total_operations{0};
    
    // 创建与CPU核心数相等的线程
    for (int i = 0; i < num_threads; ++i) {
        threads.emplace_back([this, operations_per_thread, &total_operations]() {
            for (int j = 0; j < operations_per_thread; ++j) {
                {
                    SpinLock lock(spin_mutex);
                    // 模拟临界区操作
                    volatile int temp = shared_counter.load();
                    temp++;
                    shared_counter.store(temp);
                }
                total_operations++;
            }
        });
    }
    
    // 等待所有线程完成
    for (auto& thread : threads) {
        thread.join();
    }
    
    // 验证操作总数
    EXPECT_EQ(total_operations.load(), num_threads * operations_per_thread);
    EXPECT_EQ(shared_counter.load(), num_threads * operations_per_thread);
}

/*!
 * \brief 测试锁的竞争情况
 * 
 * \details 验证多个线程竞争同一个锁时的行为
 */
TEST_F(SpinMutexTest, TestLockContention) {
    const int num_threads = 8;
    const int work_duration_ms = 1;  // 每次持锁时间
    std::vector<std::thread> threads;
    std::atomic<int> successful_locks{0};
    
    auto start_time = std::chrono::high_resolution_clock::now();
    
    // 创建多个线程竞争锁
    for (int i = 0; i < num_threads; ++i) {
        threads.emplace_back([this, work_duration_ms, &successful_locks, i]() {
            for (int j = 0; j < 10; ++j) {
                {
                    SpinLock lock(spin_mutex);
                    successful_locks++;
                    
                    // 模拟一些工作（持锁时间）
                    auto work_start = std::chrono::high_resolution_clock::now();
                    while (std::chrono::duration_cast<std::chrono::milliseconds>(
                        std::chrono::high_resolution_clock::now() - work_start).count() < work_duration_ms) {
                        // 忙等待
                        std::this_thread::yield();
                    }
                }
                
                // 释放锁后稍作休息
                std::this_thread::sleep_for(std::chrono::microseconds(100));
            }
        });
    }
    
    // 等待所有线程完成
    for (auto& thread : threads) {
        thread.join();
    }
    
    auto end_time = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time);
    
    // 验证所有锁操作都成功
    EXPECT_EQ(successful_locks.load(), num_threads * 10);
    
    std::cout << "锁竞争测试完成，耗时: " << duration.count() << " 毫秒" << std::endl;
    std::cout << "成功获取锁次数: " << successful_locks.load() << std::endl;
}

/*!
 * \brief 测试异常安全性
 * 
 * \details 验证在异常情况下锁能够正确释放
 */
TEST_F(SpinMutexTest, TestExceptionSafety) {
    // 测试RAII锁在异常情况下的自动释放
    bool exception_caught = false;
    
    try {
        SpinLock lock(spin_mutex);
        // 模拟可能抛出异常的操作
        throw std::runtime_error("测试异常");
    } catch (const std::exception& e) {
        exception_caught = true;
    }
    
    EXPECT_TRUE(exception_caught);
    
    // 验证锁已经被释放，可以重新获取
    EXPECT_NO_THROW({
        SpinLock lock(spin_mutex);
        volatile int temp = 42;
        (void)temp;
    });
}

/*!
 * \brief 测试性能特性
 * 
 * \details 比较SpinMutex与std::mutex的性能差异
 */
TEST_F(SpinMutexTest, TestPerformanceCharacteristics) {
    const int iterations = 100000;
    
    // 测试SpinMutex性能
    auto start_spin = std::chrono::high_resolution_clock::now();
    for (int i = 0; i < iterations; ++i) {
        SpinLock lock(spin_mutex);
        shared_counter++;
    }
    auto end_spin = std::chrono::high_resolution_clock::now();
    auto duration_spin = std::chrono::duration_cast<std::chrono::microseconds>(end_spin - start_spin);
    
    // 重置计数器
    shared_counter = 0;
    
    // 测试std::mutex性能（作为对比）
    std::mutex std_mutex;
    auto start_std = std::chrono::high_resolution_clock::now();
    for (int i = 0; i < iterations; ++i) {
        std::lock_guard<std::mutex> lock(std_mutex);
        shared_counter++;
    }
    auto end_std = std::chrono::high_resolution_clock::now();
    auto duration_std = std::chrono::duration_cast<std::chrono::microseconds>(end_std - start_std);
    
    std::cout << "性能对比 (" << iterations << " 次操作):" << std::endl;
    std::cout << "  SpinMutex: " << duration_spin.count() << " 微秒" << std::endl;
    std::cout << "  std::mutex: " << duration_std.count() << " 微秒" << std::endl;
    
    // 验证两种锁都能正确工作
    EXPECT_EQ(shared_counter.load(), iterations);
    
    // 性能测试不做严格断言，因为结果可能因系统而异
    // 但SpinMutex在短临界区情况下通常应该更快
    EXPECT_GT(duration_spin.count(), 0);
    EXPECT_GT(duration_std.count(), 0);
}

/*!
 * \brief 测试短临界区场景
 * 
 * \details 验证SpinMutex在短临界区场景下的优势
 */
TEST_F(SpinMutexTest, TestShortCriticalSection) {
    const int num_threads = 4;
    const int operations_per_thread = 10000;
    std::vector<std::thread> threads;
    
    auto start_time = std::chrono::high_resolution_clock::now();
    
    // 创建多个线程执行短临界区操作
    for (int i = 0; i < num_threads; ++i) {
        threads.emplace_back([this, operations_per_thread]() {
            for (int j = 0; j < operations_per_thread; ++j) {
                SpinLock lock(spin_mutex);
                // 非常短的临界区：只是简单的计数器增加
                shared_counter++;
            }
        });
    }
    
    // 等待所有线程完成
    for (auto& thread : threads) {
        thread.join();
    }
    
    auto end_time = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time);
    
    // 验证结果正确性
    EXPECT_EQ(shared_counter.load(), num_threads * operations_per_thread);
    
    std::cout << "短临界区测试完成，耗时: " << duration.count() << " 毫秒" << std::endl;
    std::cout << "总操作数: " << shared_counter.load() << std::endl;
}

/*!
 * \brief 测试内存序和原子操作
 * 
 * \details 验证SpinMutex的内存序保证
 */
TEST_F(SpinMutexTest, TestMemoryOrdering) {
    const int num_threads = 2;
    std::atomic<bool> ready{false};
    std::atomic<int> data{0};
    std::vector<std::thread> threads;
    
    // 线程1：写入数据
    threads.emplace_back([this, &ready, &data]() {
        {
            SpinLock lock(spin_mutex);
            data.store(42, std::memory_order_relaxed);
            ready.store(true, std::memory_order_release);
        }
    });
    
    // 线程2：读取数据
    threads.emplace_back([this, &ready, &data]() {
        while (!ready.load(std::memory_order_acquire)) {
            std::this_thread::yield();
        }
        
        {
            SpinLock lock(spin_mutex);
            int value = data.load(std::memory_order_relaxed);
            EXPECT_EQ(value, 42);
        }
    });
    
    // 等待所有线程完成
    for (auto& thread : threads) {
        thread.join();
    }
}

/*!
 * \brief 测试锁的公平性
 * 
 * \details 验证SpinMutex在多线程竞争时的公平性
 */
TEST_F(SpinMutexTest, TestFairness) {
    const int num_threads = 4;
    const int operations_per_thread = 100;
    std::vector<std::thread> threads;
    std::vector<std::atomic<int>> thread_counters(num_threads);
    
    // 初始化计数器
    for (auto& counter : thread_counters) {
        counter.store(0);
    }
    
    // 创建多个线程竞争锁
    for (int i = 0; i < num_threads; ++i) {
        threads.emplace_back([this, i, operations_per_thread, &thread_counters]() {
            for (int j = 0; j < operations_per_thread; ++j) {
                SpinLock lock(spin_mutex);
                thread_counters[i]++;
                shared_counter++;
                
                // 稍微增加临界区时间，让竞争更明显
                volatile int temp = 0;
                for (int k = 0; k < 10; ++k) {
                    temp += k;
                }
            }
        });
    }
    
    // 等待所有线程完成
    for (auto& thread : threads) {
        thread.join();
    }
    
    // 验证总数正确
    EXPECT_EQ(shared_counter.load(), num_threads * operations_per_thread);
    
    // 检查各线程的操作数（不要求完全公平，但不应该有线程饿死）
    std::cout << "公平性测试结果:" << std::endl;
    for (int i = 0; i < num_threads; ++i) {
        int count = thread_counters[i].load();
        std::cout << "  线程 " << i << ": " << count << " 次操作" << std::endl;
        EXPECT_GT(count, 0);  // 每个线程都应该至少执行一些操作
        EXPECT_EQ(count, operations_per_thread);  // 每个线程都应该完成所有操作
    }
}

/*!
 * \brief 测试极端并发情况
 * 
 * \details 验证SpinMutex在极端并发情况下的稳定性
 */
TEST_F(SpinMutexTest, TestExtremeConcurrency) {
    const int num_threads = std::max(16, static_cast<int>(std::thread::hardware_concurrency() * 2));
    const int operations_per_thread = 1000;
    std::vector<std::thread> threads;
    std::atomic<int> error_count{0};
    
    // 创建大量线程
    for (int i = 0; i < num_threads; ++i) {
        threads.emplace_back([this, operations_per_thread, &error_count, i]() {
            try {
                for (int j = 0; j < operations_per_thread; ++j) {
                    {
                        SpinLock lock(spin_mutex);
                        int old_value = shared_counter.load();
                        shared_counter.store(old_value + 1);
                        
                        // 验证没有竞争条件
                        if (shared_counter.load() != old_value + 1) {
                            error_count++;
                        }
                    }
                    
                    // 偶尔让出CPU
                    if (j % 100 == 0) {
                        std::this_thread::yield();
                    }
                }
            } catch (...) {
                error_count++;
            }
        });
    }
    
    // 等待所有线程完成
    for (auto& thread : threads) {
        thread.join();
    }
    
    // 验证结果
    EXPECT_EQ(error_count.load(), 0);
    EXPECT_EQ(shared_counter.load(), num_threads * operations_per_thread);
    
    std::cout << "极端并发测试完成:" << std::endl;
    std::cout << "  线程数: " << num_threads << std::endl;
    std::cout << "  总操作数: " << shared_counter.load() << std::endl;
    std::cout << "  错误数: " << error_count.load() << std::endl;
} 